unit uGlsTreeUnit;

interface

uses
  System.SysUtils,
  Vcl.Dialogs;

procedure LoadTreeDefinition(FileName: string);
{ Really bad practice.. duplicated from GlsTreeFrm.. Need to make more OOPish
  This still requires an Initializer so it loads the Leaf base 0 shape
  Main program does it... so far }
procedure LoadLeafShape(FileName: string; InShape: Integer);
procedure LoadFruitShape(FileName: string);

implementation

uses
  fGlsTreedemo,
  uGlsTree,
  uModelParameters,
  uConstants;

procedure LoadTreeDefinition(FileName: string);
{ Pre: FileName should point to an existing file.
  Post: The current model parameters have been set to the model parameters
  loaded from the tree definition file FileName. }
var
  f: TextFile;
  Newbie: Boolean;
  s: String;
  function GetNextValue: string;
  { Pre: f is assigned to a valid tree definition file.
    Ret: The next model parameter value read from f. }
  var
    Dummy: string;
  begin
    Readln(f, Dummy);
    Result := Dummy;
  end;

begin
  Newbie := False;
  try
    AssignFile(f, FileName);
    Reset(f);
    Readln(f, s);
    Readln(f, s);
    Readln(f, s);
    Readln(f, s);
    Readln(f, s);
    Readln(f, s);
    GlobalLevelsNumber := strtoint(s);
    FModelParameters := TModelParameters.Create(GlobalLevelsNumber);
    Reset(f);
    { Skip the header, 2nd line of text is version for changes }
    Readln(f, s);
    Readln(f, s);
    If s = TREAL_VERSION then
      Newbie := True;
    try
      { Initialize the model parameters class }
      with FModelParameters do
      begin
        { Update the tree definition filename edit box }
        { TreeDefFileNameEdit.Text := FileName; }
        { Save the item indices of the comboboxes }
        Shape := strtoint(GetNextValue);
        LeafShape := strtoint(GetNextValue);

        Readln(f, s); { LevelsNumberEdit.Text:= GetNextValue; }
        { GlobalLevelsNumber:=strtoint(s); }
        { Levels := CurrentLevelsNumber; }
        Lobes := strtoint(GetNextValue);
        BaseSplits := strtoint(GetNextValue);
        nCurveRes[0] := strtoint(GetNextValue);
        Leaves := strtoint(GetNextValue);
        nVertices[0] := strtoint(GetNextValue);

        Scale := strtofloat(GetNextValue);
        ScaleV := strtofloat(GetNextValue);
        BaseSize := strtofloat(GetNextValue);
        ZScale := strtofloat(GetNextValue);
        ZScaleV := strtofloat(GetNextValue);
        Ratio := strtofloat(GetNextValue);
        RatioPower := strtofloat(GetNextValue);
        LobeDepth := strtofloat(GetNextValue);
        Flare := strtofloat(GetNextValue);
        LeafScale := strtofloat(GetNextValue);
        LeafScaleX := strtofloat(GetNextValue);
        LeafQuality := strtofloat(GetNextValue);
        AttractionUp := strtofloat(GetNextValue);
        PruneRatio := strtofloat(GetNextValue);
        PruneWidth := strtofloat(GetNextValue);
        PruneWidthPeak := strtofloat(GetNextValue);
        PrunePowerLow := strtofloat(GetNextValue);
        PrunePowerHigh := strtofloat(GetNextValue);
        Scale0 := strtofloat(GetNextValue);
        ScaleV0 := strtofloat(GetNextValue);
        nLength[0] := strtofloat(GetNextValue);
        nLengthV[0] := strtofloat(GetNextValue);
        nTaper[0] := strtofloat(GetNextValue);
        nSegSplits[0] := strtofloat(GetNextValue);
        nSplitAngle[0] := strtofloat(GetNextValue);
        nSplitAngleV[0] := strtofloat(GetNextValue);
        nCurveBack[0] := strtofloat(GetNextValue);
        nCurve[0] := strtofloat(GetNextValue);
        nCurveV[0] := strtofloat(GetNextValue);

        { LevelsNumberEdit.GetValue - 2 is used in the following loop, since the
          last recursion level is the leaf level. So we have in fact
          LevelsNumberEdit.GetValue - 1 stem parameter tabs. }
        { Trunk0 1,2,3,4,5... Leaf 6 = 7 levels }
        If GlobalLevelsNumber > 1 then
        begin { Trunk0 1,... Leaf x = 3 levels }
          nBranches[1] := strtoint(GetNextValue);
          nVertices[1] := strtoint(GetNextValue);
          nCurveRes[1] := strtoint(GetNextValue);
        end;
        If GlobalLevelsNumber > 2 then
        begin { Trunk0 1,2... Leaf x = 4 levels }
          nBranches[2] := strtoint(GetNextValue);
          nVertices[2] := strtoint(GetNextValue);
          nCurveRes[2] := strtoint(GetNextValue);
        end;
        If GlobalLevelsNumber > 3 then
        begin { Trunk0 1,2,3... Leaf x = 5 levels }
          nBranches[3] := strtoint(GetNextValue);
          nVertices[3] := strtoint(GetNextValue);
          nCurveRes[3] := strtoint(GetNextValue);
        end;
        If GlobalLevelsNumber > 4 then
        begin { Trunk0 1,2,3,4... Leaf x = 6 levels }
          nBranches[4] := strtoint(GetNextValue);
          nVertices[4] := strtoint(GetNextValue);
          nCurveRes[4] := strtoint(GetNextValue);
        end;
        If GlobalLevelsNumber > 5 then
        begin { Trunk0 1,2,3,4,5... Leaf x = 7 levels }
          nBranches[5] := strtoint(GetNextValue);
          nVertices[5] := strtoint(GetNextValue);
          nCurveRes[5] := strtoint(GetNextValue);
        end;
        If GlobalLevelsNumber > 6 then
        begin { Trunk0 1,2,3,4,5... Leaf x = 7 levels }
          nBranches[6] := strtoint(GetNextValue);
          nVertices[6] := strtoint(GetNextValue);
          nCurveRes[6] := strtoint(GetNextValue);
        end;
        { Save the values belonging to all float edit input components
          belonging to the stem parameters }

        { LevelsNumberEdit.GetValue - 2 is used in the following loop, since the
          last recursion level is the leaf level. So we have in fact
          LevelsNumberEdit.GetValue - 1 stem parameter tabs. }
        If GlobalLevelsNumber > 1 then
        begin { Trunk0 1,... Leaf x = 3 levels  7 }
          nLength[1] := strtofloat(GetNextValue);
          nLengthV[1] := strtofloat(GetNextValue);
          nTaper[1] := strtofloat(GetNextValue);
          nDownAngle[1] := strtofloat(GetNextValue);
          nDownAngleV[1] := strtofloat(GetNextValue);
          nRotate[1] := strtofloat(GetNextValue);
          nRotateV[1] := strtofloat(GetNextValue);
          nCurveBack[1] := strtofloat(GetNextValue);
          nCurve[1] := strtofloat(GetNextValue);
          nCurveV[1] := strtofloat(GetNextValue);
          nSplitAngle[1] := strtofloat(GetNextValue);
          nSplitAngleV[1] := strtofloat(GetNextValue);
          nSegSplits[1] := strtofloat(GetNextValue);
        End;
        If GlobalLevelsNumber > 2 then
        begin { Trunk0 1,... Leaf x = 3 levels  7 }
          nLength[2] := strtofloat(GetNextValue);
          nLengthV[2] := strtofloat(GetNextValue);
          nTaper[2] := strtofloat(GetNextValue);
          nDownAngle[2] := strtofloat(GetNextValue);
          nDownAngleV[2] := strtofloat(GetNextValue);
          nRotate[2] := strtofloat(GetNextValue);
          nRotateV[2] := strtofloat(GetNextValue);
          nCurveBack[2] := strtofloat(GetNextValue);
          nCurve[2] := strtofloat(GetNextValue);
          nCurveV[2] := strtofloat(GetNextValue);
          nSplitAngle[2] := strtofloat(GetNextValue);
          nSplitAngleV[2] := strtofloat(GetNextValue);
          nSegSplits[2] := strtofloat(GetNextValue);
        End;
        If GlobalLevelsNumber > 3 then
        begin { Trunk0 1,... Leaf x = 3 levels  7 }
          nLength[3] := strtofloat(GetNextValue);
          nLengthV[3] := strtofloat(GetNextValue);
          nTaper[3] := strtofloat(GetNextValue);
          nDownAngle[3] := strtofloat(GetNextValue);
          nDownAngleV[3] := strtofloat(GetNextValue);
          nRotate[3] := strtofloat(GetNextValue);
          nRotateV[3] := strtofloat(GetNextValue);
          nCurveBack[3] := strtofloat(GetNextValue);
          nCurve[3] := strtofloat(GetNextValue);
          nCurveV[3] := strtofloat(GetNextValue);
          nSplitAngle[3] := strtofloat(GetNextValue);
          nSplitAngleV[3] := strtofloat(GetNextValue);
          nSegSplits[3] := strtofloat(GetNextValue);
        End;
        If GlobalLevelsNumber > 4 then
        begin { Trunk0 1,... Leaf x = 3 levels  7 }
          nLength[4] := strtofloat(GetNextValue);
          nLengthV[4] := strtofloat(GetNextValue);
          nTaper[4] := strtofloat(GetNextValue);
          nDownAngle[4] := strtofloat(GetNextValue);
          nDownAngleV[4] := strtofloat(GetNextValue);
          nRotate[4] := strtofloat(GetNextValue);
          nRotateV[4] := strtofloat(GetNextValue);
          nCurveBack[4] := strtofloat(GetNextValue);
          nCurve[4] := strtofloat(GetNextValue);
          nCurveV[4] := strtofloat(GetNextValue);
          nSplitAngle[4] := strtofloat(GetNextValue);
          nSplitAngleV[4] := strtofloat(GetNextValue);
          nSegSplits[4] := strtofloat(GetNextValue);
        End;
        If GlobalLevelsNumber > 5 then
        begin { Trunk0 1,... Leaf x = 3 levels  7 }
          nLength[5] := strtofloat(GetNextValue);
          nLengthV[5] := strtofloat(GetNextValue);
          nTaper[5] := strtofloat(GetNextValue);
          nDownAngle[5] := strtofloat(GetNextValue);
          nDownAngleV[5] := strtofloat(GetNextValue);
          nRotate[5] := strtofloat(GetNextValue);
          nRotateV[5] := strtofloat(GetNextValue);
          nCurveBack[5] := strtofloat(GetNextValue);
          nCurve[5] := strtofloat(GetNextValue);
          nCurveV[5] := strtofloat(GetNextValue);
          nSplitAngle[5] := strtofloat(GetNextValue);
          nSplitAngleV[5] := strtofloat(GetNextValue);
          nSegSplits[5] := strtofloat(GetNextValue);
        End;
        If GlobalLevelsNumber > 6 then
        begin { Trunk0 1,... Leaf x = 3 levels  7 }
          nLength[6] := strtofloat(GetNextValue);
          nLengthV[6] := strtofloat(GetNextValue);
          nTaper[6] := strtofloat(GetNextValue);
          nDownAngle[6] := strtofloat(GetNextValue);
          nDownAngleV[6] := strtofloat(GetNextValue);
          nRotate[6] := strtofloat(GetNextValue);
          nRotateV[6] := strtofloat(GetNextValue);
          nCurveBack[6] := strtofloat(GetNextValue);
          nCurve[6] := strtofloat(GetNextValue);
          nCurveV[6] := strtofloat(GetNextValue);
          nSplitAngle[6] := strtofloat(GetNextValue);
          nSplitAngleV[6] := strtofloat(GetNextValue);
          nSegSplits[6] := strtofloat(GetNextValue);
        End;

        { Finally, save the leaf color, and the leaf color variation boolean }
        LeafColor := strtoint(GetNextValue);
        if 'true' = GetNextValue then
          LeafColorVariation := True
        else
          LeafColorVariation := False;
        If Newbie then
        begin
          Readln(f, s); { Line that says this is new stuff }
          { NOW Write ALL the new data }
          TreeSeed := strtoint(GetNextValue);
          Health := strtoint(GetNextValue);
          Season := strtoint(GetNextValue);
          TreeImageFile := GetNextValue;
          TreeShapeFile := GetNextValue;
          TreeBarkFile := GetNextValue;
          TreeColor := strtoint(GetNextValue);
          if 'true' = GetNextValue then
            TreeColorVariation := True
          else
            TreeColorVariation := False;
          Distance := strtoint(GetNextValue);
          WindStrength := strtoint(GetNextValue);
          WindGust := strtoint(GetNextValue);
          WindFrom := strtoint(GetNextValue);
          SunHeight := strtoint(GetNextValue);
          SunStrength := strtoint(GetNextValue);
          SunFrom := strtoint(GetNextValue);
          LeafImageFile := GetNextValue;
          LeafShapeFile := GetNextValue;
          LoadLeafShape(LeafShapeFile, LeafShape);
          LeafTextureFile := GetNextValue;
          LeafLocation := strtoint(GetNextValue);
          FLeafsPer := strtoint(GetNextValue);
          LeafGrouping := strtoint(GetNextValue);
          LeafBackColor := strtoint(GetNextValue);
          if 'true' = GetNextValue then
            LeafBackColorVariation := True
          else
            LeafBackColorVariation := False;
          FruitPattern := strtoint(GetNextValue);
          FruitScale := strtofloat(GetNextValue);
          FruitScaleX := strtofloat(GetNextValue);
          Fruits := strtoint(GetNextValue);
          FruitPer := strtoint(GetNextValue);
          FruitLocation := strtoint(GetNextValue);
          FruitImageFile := GetNextValue;
          FruitShapeFile := GetNextValue;
          LoadFruitShape(FruitShapeFile);
          FruitTextureFile := GetNextValue;
          if 'true' = GetNextValue then
            FruitColorVariation := True
          else
            FruitColorVariation := False;
          FruitColor := strtoint(GetNextValue);
          nLeaves[0] := strtoint(GetNextValue);
          nLeaves[1] := strtoint(GetNextValue);
          nLeaves[2] := strtoint(GetNextValue);
          nLeaves[3] := strtoint(GetNextValue);
          nLeaves[4] := strtoint(GetNextValue);
          nLeaves[5] := strtoint(GetNextValue);
          nLeaves[6] := strtoint(GetNextValue);
        end; { newbie }
        { Adjust the current low level parameters according to
          the high level parameters }

        case Season of
          0: { Winter }
            begin
              Leaves := 0;
              Fruits := 0;
            end;
          1: { Spring }
            begin
              LeafScale := LeafScale / 2;
              LeafScaleX := LeafScaleX / 2;
              FruitScale := FruitScale / 2;
              FruitScaleX := FruitScaleX / 2;
            end;
          { 2: Summer (no adjustment needed) }
          3: { Autumn }
            begin
              LeafColor := $2A8AE4;
              LeafColorVariation := True;
              LeafBackColor := $2A8AE4;
              LeafBackColorVariation := True;
              FruitColorVariation := True;
              FruitColor := $2A8AE4;
            end;
        end;
        { Done in GlsTree now... }
        { Leaves := Leaves - (Leaves * (1 - (101 div (Health + 1)))); }

      end; { with Model }
    except
      { On known exceptions show an error message. }
      on EConvertError do
        MessageDlg(FileName + ' is not a valid tree definition file!', mtError,
          [mbOK], 0);
      on EInOutError do
        MessageDlg('Error while reading ' + FileName + '!', mtError, [mbOK], 0);
      else
        { Show a general error message }
        MessageDlg('Unknow error while reading ' + FileName + '!', mtError,
          [mbOK], 0);
    end;
  finally
    CloseFile(f);
  end;
end;

// -----------------------------------------------------
// -----------------------------------------------------
procedure LoadLeafShape(FileName: string; InShape: Integer);
var
  f: TextFile;
  { ImageToo:Boolean; }
  i: Integer;
  ss, s: string;
begin
  try
    AssignFile(f, FileName);
    Reset(f);
    try
      Readln(f, s); { showmessage('0: '+s); }
      LeafPolygonVerticesNumber[InShape] := strtoint(s);
      Readln(f, s);
      { If strtoint(s)=1 then ImageToo:=True else ImageToo:=False; }
      SetLength(LeafPolygonVertices[InShape],
        LeafPolygonVerticesNumber[InShape] + 1, 3);
      SetLength(LeafPolyImageVertices, LeafPolygonVerticesNumber[InShape] + 1);
      For i := 0 to LeafPolygonVerticesNumber[InShape] do
      begin
        Readln(f, s); { Copy(S; Index, Count: Integer): string; }
        ss := Copy(s, 0, Pos(',', s) - 1);
        LeafPolyImageVertices[i, 0] := strtoint(ss); { showmessage('1: '+ss); }
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss; { showmessage('2a: '+ss); }
        ss := Copy(s, 0, Pos(',', s) - 1); { showmessage('2b: '+ss); }
        LeafPolyImageVertices[i, 1] := strtoint(ss);
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss;
        ss := Copy(s, 0, Pos(',', s) - 1); { showmessage('x: '+ss); }
        LeafPolygonVertices[1, i, 0] := strtofloat(ss);
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss;
        ss := Copy(s, 0, Pos(',', s) - 1);
        LeafPolygonVertices[1, i, 1] := strtofloat(ss);
        { showmessage('y: '+ss); }
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss; { showmessage('z: '+ss); }
        { ss:=Copy(s,0,Pos(',', S)); }
        LeafPolygonVertices[1, i, 2] := strtofloat(s);
      end;
      { If (not ImageToo) then ComputeLeafImageCoords; }
    except
      { On known exceptions show an error message. }
      on EConvertError do
        MessageDlg(FileName + ' is not a valid tree definition file!', mtError,
          [mbOK], 0);
      on EInOutError do
        MessageDlg('Error while writing ' + FileName + '!', mtError, [mbOK], 0);
      else
        { Show a general error message }
        MessageDlg('Unknown error while reading ' + FileName + '!', mtError,
          [mbOK], 0);
    end;
  finally
    CloseFile(f);
  end;
end;

{ GlsShapePath FruitShape If loaded then use ELSE a SPhere! }
procedure LoadFruitShape(FileName: string);
var
  f: TextFile;
  { ImageToo:Boolean; }
  { x,y, } i: Integer;
  ss, s: string;
begin
  try
    AssignFile(f, FileName);
    Reset(f);
    try
      Readln(f, s);
      FruitPolygonVerticesNumber := strtoint(s);
      Readln(f, s);
      { If strtoint(s)=1 then ImageToo:=True else ImageToo:=False; }
      Readln(f, s); { x:=strtoint(s); }
      Readln(f, s); { y:=strtoint(s); }
      SetLength(FruitPolyImageVertices, FruitPolygonVerticesNumber + 1);
      SetLength(FruitPolygonVertices, FruitPolygonVerticesNumber + 1);
      For i := 0 to FruitPolygonVerticesNumber do
      begin { FruitPolyImageVertices }
        Readln(f, s);
        ss := Copy(s, 0, Pos(',', s) - 1);
        FruitPolyImageVertices[i, 0] := strtoint(ss);
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss;
        ss := Copy(s, 0, Pos(',', s) - 1);
        FruitPolyImageVertices[i, 1] := strtoint(ss);
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss;
        ss := Copy(s, 0, Pos(',', s) - 1);
        FruitPolygonVertices[i, 0] := strtofloat(ss);
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss;
        ss := Copy(s, 0, Pos(',', s) - 1);
        FruitPolygonVertices[i, 1] := strtofloat(ss);
        ss := Copy(s, Pos(',', s) + 1, Length(s));
        s := ss;
        { ss:=Copy(s,0,Pos(',', S)); }
        FruitPolygonVertices[i, 2] := strtofloat(s);
      end;
      { If (not ImageToo) then ComputeFruitImageCoords(x,y); }

    except
      { On known exceptions show an error message. }
      on EConvertError do
        MessageDlg(FileName + ' is not a valid tree definition file!', mtError,
          [mbOK], 0);
      on EInOutError do
        MessageDlg('Error while writing ' + FileName + '!', mtError, [mbOK], 0);
      else
        { Show a general error message }
        MessageDlg('Unknown error while reading ' + FileName + '!', mtError,
          [mbOK], 0);
    end;
  finally
    CloseFile(f);
  end;
end;

end.
